import { useState } from 'react'

const lines = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6],
]
function Square({ value, onSquareClick, className }) {
  return (
    <button className={className} onClick={onSquareClick}>
      {value}
    </button>
  )
}

function Board({ num, xIsNext, squares, onPlay, hasWinner }) {
  //   const [squares, setSquares] = useState(Array(9).fill(null)); // state 对于定义它的组件是私有的
  //   const [xIsNext, setXIsNext] = useState(true);

  //   const [status, setStatus] = useState('Next player: X')

  // Board重新渲染时，下面几行代码都会执行？
  //   let status = 'Next player: ' + (xIsNext ? 'X' : 'O')
  //   winnerLine.length == 0 ? (status = 'Next player: ' + (xIsNext ? 'X' : 'O'))
  //   if (squares) {
  //     // const winner = calculateWinner(squares)
  //     if (winner) {
  //       status = 'Winner: ' + winner.winner
  //     } else {
  //       status = '结果为平局'
  //     }
  //   }
  //   const nums = num * num

  const winner = hasWinner && calculateWinner(squares) // Board重新渲染时，下面几行代码都会执行
  function handleClick(i, row, col) {
    if (squares[i] || hasWinner) {
      return
    }

    /**
     * 不变性的重要性
     *  1 更好的支持后续 撤销和重做
     *  2 性能
     *        当你改变Board的state时，Square所有 子组件会自动重新渲染，
     *        react为了只渲染更改的子组件，会通过数据比较的方式来筛选出需要重新渲染的子组件
     *        不变性会让这个 比较过程 更加高效。
     */
    const nextSquares = squares.slice()
    nextSquares[i] = xIsNext ? 'X' : 'O'
    onPlay(nextSquares, row, col)

    // setXIsNext(!xIsNext)
    // setSquares(nextSquares); // 当你在组件中调用 set 函数时，React 也会自动更新内部的子组件。
  }

  let random = Math.random()

  // 此处改变会触发board函数 重新执行
  //   setTimeout(() => {
  //     random = Math.random()
  //     console.log(random)
  //   }, 1000)
  const squaresDom = Array(num)
    .fill(null)
    .map((_, index) => {
      return (
        <div className="board-row" key={index}>
          {Array(num)
            .fill(null)
            .map((_, index_) => {
              const sIndex = index * num + index_
              return (
                <Square
                  value={squares[sIndex]}
                  className={winner && winner.winnerLine.includes(sIndex) ? 'square active' : 'square'}
                  key={sIndex}
                  onSquareClick={() => handleClick(sIndex, index + 1, index_ + 1)}
                />
              )
            })}
        </div>
      )
    })

  return (
    <div>
      <div>random -- {random}</div>

      {squaresDom}
    </div>
  )
}

export default function Game() {
  const [winner, setWinner] = useState(null)
  const initData = [Array(9).fill(null)]
  const [history, setHistory] = useState(initData)
  const [currentMove, setCurrentMove] = useState(0)
  const [currentSort, setCurrentSort] = useState('Asc')

  const xIsNext = currentMove % 2 == 0

  const hasWinner = !!winner
  let nextStatus = ''
  if (!hasWinner) {
    nextStatus = `Next player: ${xIsNext ? 'X' : 'O'}`
    if (currentMove == 9) {
      nextStatus = '结果为平局'
    }
  } else {
    nextStatus = `winner is ${winner.winner}`
  }

  function handlePlay(nextSquares, row, col) {
    nextSquares.row = row
    nextSquares.col = col
    const winner = calculateWinner(nextSquares)
    if (winner) {
      setWinner(winner)
    }
    const squares = history.slice(0, currentMove + 1)
    const nextHistory = [...squares, nextSquares]
    setHistory(nextHistory)
    setCurrentMove(nextHistory.length - 1)
  }

  function jumpTo(nextMove) {
    setCurrentMove(nextMove) // 改变时，会触发重新render, 不会改变 其他state数据
  }

  function handleStepSorting() {
    setCurrentSort(currentSort == 'Asc' ? 'Desc' : 'Asc')
  }

  const moves = history.map((squares, move) => {
    // key 不需要是全局唯一的；它们只需要在组件及其同级组件之间是唯一的。
    const append = move > 0 ? move + '' + squares.row + '' + squares.col : move
    let desc = move == currentMove ? `You are at move ${append}` : 'back to game#' + append
    return <li key={move}>{move == currentMove ? desc : <button onClick={() => jumpTo(move)}>{desc}</button>}</li>
  })
  /**
   * 当有人获胜时，突出显示致使获胜的三个方块（当没有人获胜时，显示一条关于结果为平局的消息）。
   * 在“落子”的历史列表中以 (row, col) 格式显示每步的位置。
   */
  return (
    <div>
      <div className="status">{nextStatus}</div>
      <div className="game-info" style={{ display: 'flex', alignItems: 'flex-end' }}>
        <Board num={3} hasWinner={hasWinner} xIsNext={xIsNext} squares={history[currentMove]} onPlay={handlePlay} />
        <ol>{currentSort == 'Asc' ? moves : moves.reverse()}</ol>
      </div>
      <button onClick={handleStepSorting}>{currentSort}</button>
    </div>
  )
}
function calculateWinner(squares) {
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i]
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return {
        winner: squares[a],
        winnerLine: lines[i],
      }
    }
  }
  return null
}
